﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Yaml.Presentation.Parsing {
    public class ScannerState {
        private int line;
        private int column;
        private bool done;
        private int flowDepth;
        private SimpleKeys simpleKeys;
        private Indentation indentation;
        private int[] yamlVersion;

        public ScannerState() {
            simpleKeys = new SimpleKeys();
            indentation = new Indentation();
            done = false;
            flowDepth = 0;
            line = 0;
            column = 0;
            this.yamlVersion = new int[] { 1, 1 };
        }

        /// <summary>
        /// A collection of possible simple keys at the point in scanning
        /// </summary>
        public SimpleKeys SimpleKeys { get { return this.simpleKeys; } }
        /// <summary>
        /// A stack of indentation levels.
        /// </summary>
        public Indentation Indentation { get { return this.indentation; } }
        /// <summary>
        /// Is the scanning completed?
        /// </summary>
        public bool Done { get { return this.done; } set { this.done = value; } }
        /// <summary>
        /// The number of unclosed [ and {.  A value of zero means block context
        /// </summary>
        public int FlowDepth { get { return this.flowDepth; } }
        /// <summary>
        /// The line number of the current scan position
        /// </summary>
        public int Line { get { return line; } }
        /// <summary>
        /// The column number of the current scan position
        /// </summary>
        public int Column { get { return column; } }
        /// <summary>
        /// The string representation of the YAML version of the current "stream"
        /// </summary>
        public string YAMLVersionString {
            get { return yamlVersion[0].ToString() + '.' + yamlVersion[1]; }
        }
        /// <summary>
        /// Are we currently inside a flow style collection, i.e. inside either {...} or [...]?
        /// </summary>
        public bool NotInFlow {
            get { return this.flowDepth == 0; }
        }
        /// <summary>
        /// A simple key is required if we are not inside a flow and we are at the current level of indentation.
        /// </summary>
        public bool IsSimpleKeyRequired {
            get { return NotInFlow && Column == Indentation.Current; }
        }

        /// <summary>
        /// Set the YAML version
        /// </summary>
        public void SetYAMLVersion(int major, int minor) {
            if (major != 1) {
                throw new ScannerException("Invalid major YAML version number, " + YAMLVersionString + ", this processor only accepts 1.*");
            }
            if (minor != 1) {
                Scanner.Warning("Unrecognized minor YAML version number, " + YAMLVersionString + ", this processor is aimed at 1.1");
            }
            yamlVersion[0] = major;
            yamlVersion[1] = minor;
        }
        public void NewColumn() {
            column++;
        }
        public void NewLine() {
            column = 0;
            line++;
        }

        public void FlowStarted() {
            flowDepth++;
        }
        public void FlowEnded() {
            if (flowDepth == 0) {
                throw new InvalidOperationException("Flow Depth cannot be negative");
            }
            flowDepth--;
        }
    }
}
